package cn.bluethink.eguan.core.controller;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import cn.bluethink.eguan.core.security.Token;
import cn.bluethink.eguan.core.service.EgAcountService;
import cn.bluethink.eguan.core.service.EgFactionService;
import cn.bluethink.eguan.core.service.EgMemberService;
import cn.bluethink.eguan.core.service.EgUserService;
import cn.bluethink.eguan.model.core.EgAcount;
import cn.bluethink.eguan.model.core.EgConfigInfo;
import cn.bluethink.eguan.model.core.EgFaction;
import cn.bluethink.eguan.model.core.EgOType;
import cn.bluethink.eguan.model.core.EgObject;
import cn.bluethink.eguan.model.core.EgPurview;
import cn.bluethink.eguan.model.core.EgRole;
import cn.bluethink.eguan.model.core.EgUser;
import cn.bluethink.eguan.model.okrtask.EgTimingType;
import cn.bluethink.eguan.result.PageInfo;
import cn.bluethink.eguan.result.ResponseMessage;
import cn.bluethink.eguan.result.ResponseResult;
import cn.bluethink.eguan.utils.AESUtils;
import cn.bluethink.eguan.utils.OkrTaskUtil;

/**
 * eguan+门派控制器
 * 
 * @title 苏州中科蓝迪公司所有(c)2016-2021
 * @version 0.1.0
 * @describe
 * @author liuxn
 * @date 2018年10月16日
 * @note 修订历史： 1.liuxn于2018年10月16日构建初始版本0.1 2.wanglei于2018年10月16日实现接口功能
 *       3.wanglei于2018年11月6日补充删除门派，移交门派，更新门派的接口 4.wanglei于2018年11月7日补充获取门派详情的接口
 */
@CrossOrigin
@RestController
@RequestMapping("/eguan/v1.0/faction")
public class EgFactionController {

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private EgFactionService factionService;

    @Autowired
    private EgMemberService memberService;

    @Autowired
    private EgConfigInfo configInfo;

    @Autowired
    private EgUserService userService;

    @Autowired
    private EgAcountService acountService;

    /**
     * 根据当前用户查询其所属的门派列表（包括江湖）
     * 
     * @param uid
     * @return
     * @throws Exception
     */
    @Token
    @GetMapping("/myfaction")
    public ResponseResult<PageInfo<EgObject>> myfaction() throws Exception {
        // String token = request.getHeader("Authorization");
        Long id = (Long) request.getAttribute("userId");
        return new ResponseResult<>(ResponseMessage.OK, factionService.myfaction(id));
    }

    /**
     * 进入门派(fid为0或null，表示切换到江湖)
     * 
     * @param fid
     * @return
     * @throws Exception
     */
    @Token
    @GetMapping("/enter")
    public ResponseResult<Long> enter(@RequestParam Long fid) throws Exception {
        Long uid = (Long) request.getAttribute("userId");
        // fid为0或null，表示切换到江湖
        Long posOid = (fid == null || fid == 0) ? 0L : fid;
        Integer otype = EgOType.JIANGHU;
        if (posOid > 0L) {
            // 查看门派详情
            if (factionService.getById(posOid) == null) {
                return new ResponseResult<>(ResponseMessage.DATA_NOT_FOUND.getStatus(), "门派不存在！");
            }
            otype = EgOType.FACTION;
        }
        // 更新当前登录用户所在位置为江湖或门派
        if (!userService.updatePos(uid, otype, posOid)) {
            return new ResponseResult<>(ResponseMessage.UPDATE_FAIL.getStatus(), "进入失败！");
        }
        return new ResponseResult<>(ResponseMessage.OK, posOid);
    }

    /**
     * 获取门派的详情(包括账户详情，创建者基本信息)
     * 
     * @param fid
     * @return
     * @throws Exception
     */
    @Token
    @GetMapping("/detail")
    public ResponseResult<EgFaction> detail(@RequestParam Long fid) throws Exception {
        EgFaction faction = factionService.detail(fid);
        if (faction != null) {
            return new ResponseResult<>(ResponseMessage.OK, faction);
        }
        return new ResponseResult<>(ResponseMessage.DATA_NOT_FOUND.getStatus(), "门派不存在！");
    }

    /**
     * 修改门派基本信息(门派名称，门派图标)
     * 
     * @param fid
     * @return
     * @throws Exception
     */
    @Token(purviews = { EgPurview.FACTION_MG })
    @PostMapping("/update")
    public ResponseResult<EgFaction> update(@RequestBody EgFaction faction) throws Exception {
        Long uid = (Long) request.getAttribute("userId");
        // 门派ID不为空
        Long fid = faction.getId();
        if (fid == null || fid == 0) {
            return new ResponseResult<>(ResponseMessage.NOTNULL_ID);
        }
        // 获取该门派详情信息
        EgFaction oldFaction = factionService.detail(fid);
        if (oldFaction == null) {
            return new ResponseResult<>(ResponseMessage.DATA_NOT_FOUND.getStatus(), "门派不存在！");
        }
        // 判断当前用户是否隶属本门派
        if (memberService.queryById(fid, uid) == null) {
            return new ResponseResult<>(ResponseMessage.INADEQUATE_PERMISSIONS.getStatus(), "非本派成员不能操作！");
        }
        // 待更新的季度年的开始月份必须为1-12月
        Integer bmonth = faction.getBmonth();
        if (bmonth != null && (bmonth < 1 || bmonth > 12)) {
            return new ResponseResult<>(ResponseMessage.UPDATE_FAIL.getStatus(), "季度年的开始月份设置不规范！");
        }
        // 更新门派基本信息
        EgFaction result = factionService.update(oldFaction, faction);
        if (result != null) {
            return new ResponseResult<>(ResponseMessage.OK, result);
        }
        return new ResponseResult<>(ResponseMessage.UPDATE_FAIL.getStatus(), "门派信息更新失败！");
    }

    /**
     * 删除门派（江湖中的审核权限 或者 门派中具有门派管理权限）
     * 备注：审核权限的进来之后直接删除操作；门派管理权限的进来需要判定是否隶属本门派成员。方法内部都必须进行权限判断，所以无需进行token权限验证
     * 
     * @param fid
     * @param name
     * @return
     * @throws Exception
     */
    @Token(purviews = { EgPurview.OBJECT_CHECK, EgPurview.FACTION_MG })
    @PostMapping("/del")
    public ResponseResult<Long> del(@RequestParam Long fid, @RequestParam String name) throws Exception {
        EgFaction faction = factionService.detail(fid);
        if (faction == null) {
            return new ResponseResult<>(ResponseMessage.NOTNULL_ID.getStatus(), "待删除的门派不存在！");
        }
        // 门派全称必须匹配
        if (!name.trim().equals(faction.getName())) {
            return new ResponseResult<>(ResponseMessage.DELETE_FAIL.getStatus(), "请正确输入门派的全称！");
        }
        Long uid = (Long) request.getAttribute("userId");
        // 删除操作
        if (factionService.delete(fid, uid)) {
            return new ResponseResult<>(ResponseMessage.OK, fid);
        }
        return new ResponseResult<>(ResponseMessage.DELETE_FAIL);
    }

    /**
     * 移交门派(移交帮主身份给门派其他成员)
     * 
     * @param fid
     * @param toUid
     *            被转移的门派成员ID
     * @return
     * @throws Exception
     */
    @Token(purviews = { EgPurview.FACTION_MG })
    @PostMapping("/transfer")
    public ResponseResult<Boolean> transfer(@RequestParam Long fid, @RequestParam Long toUid) throws Exception {
        // 判断被移交者是否是本门派成员
        EgUser toUser = memberService.queryById(fid, toUid);
        if (toUser == null) {
            return new ResponseResult<>(ResponseMessage.INADEQUATE_PERMISSIONS.getStatus(), "非本派成员不能移交！");
        }
        // 获取该门派中的帮主
        EgUser cheaf = memberService.queryByRole(fid, (EgRole.CHEAF | EgRole.MEMBER));
        if (cheaf.getId().equals(toUid)) {
            return new ResponseResult<>(ResponseMessage.TRANCFER_FAIL.getStatus(), "被移交者已经是帮主！");
        }
        // 移交帮主身份
        if (factionService.transfer(fid, cheaf, toUser)) {
            return new ResponseResult<>(ResponseMessage.OK, true);
        }
        return new ResponseResult<>(ResponseMessage.TRANCFER_FAIL);
    }

    /**
     * 门派账户充值
     * 
     * @param fid
     * @param bt
     * @return
     * @throws Exception
     */
    @Token(purviews = { EgPurview.FACTION_RECHARGE })
    @PostMapping("/recharge")
    public ResponseResult<Boolean> recharge(@RequestParam Long fid, @RequestParam Integer bt) throws Exception {
        // 获取江湖中的账户详情
        EgAcount jAcount = acountService.query(configInfo.getAcountId());
        if (jAcount == null) {
            return new ResponseResult<>(ResponseMessage.DATA_NOT_FOUND);
        }
        // 根据门派ID查看门派详情
        EgFaction faction = factionService.detail(fid);
        if (faction == null) {
            return new ResponseResult<>(ResponseMessage.DATA_NOT_FOUND);
        }
        // 获取门派的唯一账户
        EgAcount fAcount = acountService.query(faction.getAcount().getId());
        if (fAcount == null) {
            return new ResponseResult<>(ResponseMessage.DATA_NOT_FOUND);
        }
        // 充值
        if (factionService.recharge(jAcount, fAcount, faction, bt)) {
            return new ResponseResult<>(ResponseMessage.OK, true);
        }
        return new ResponseResult<>(ResponseMessage.RECHARGE_FAIL);
    }

    /**
     * 开通禅道服务
     * 
     * 拥有门派管理权限的用户可开通该服务，可修改该服务地址
     * 
     * @param ztServerAddress
     * @return
     * @throws Exception
     */
    @Token(purviews = { EgPurview.FACTION_MG })
    @PostMapping("/ztServer")
    public ResponseResult<String> ztServerOpen(@RequestParam Long fid, @RequestParam String ztServerAddress)
            throws Exception {
        if (StringUtils.isBlank(ztServerAddress))
            return new ResponseResult<>(ResponseMessage.BAD_REQUEST.getStatus(), "禅道服务地址不能为null！");
        Long uid = (Long) request.getAttribute("userId");
        // 判断当前用户是否隶属本门派
        if (memberService.queryById(fid, uid) == null) {
            return new ResponseResult<>(ResponseMessage.INADEQUATE_PERMISSIONS.getStatus(), "非本派成员不能操作！");
        }
        return new ResponseResult<>(ResponseMessage.OK, factionService.updateZtServer(fid, ztServerAddress));
    }

    /**
     * 关闭禅道服务
     * 
     * 拥有门派管理权限的用户可关闭该服务，即服务地址调整为null
     * 
     * @param ztServerAddress
     * @return
     * @throws Exception
     */
    @Token(purviews = { EgPurview.FACTION_MG })
    @PostMapping("/ztServerClose")
    public ResponseResult<String> ztServerClose(@RequestParam Long fid) throws Exception {
        Long uid = (Long) request.getAttribute("userId");
        // 判断当前用户是否隶属本门派
        if (memberService.queryById(fid, uid) == null) {
            return new ResponseResult<>(ResponseMessage.INADEQUATE_PERMISSIONS.getStatus(), "非本派成员不能操作！");
        }
        return new ResponseResult<>(ResponseMessage.OK, factionService.updateZtServer(fid, ""));
    }

    /**
     * 获取禅道服务地址，用于前端判断是否渲染禅道模块
     * 
     * @param fid
     * @return
     * @throws Exception
     */
    @Token
    @GetMapping("/ztServerAddress")
    public ResponseResult<String> ztServerAddress(@RequestParam Long fid) throws Exception {
        Long uid = (Long) request.getAttribute("userId");
        // 判断当前用户是否隶属本门派
        if (memberService.queryById(fid, uid) == null) {
            return new ResponseResult<>(ResponseMessage.INADEQUATE_PERMISSIONS.getStatus(), "非本派成员不能操作！");
        }
        return new ResponseResult<>(ResponseMessage.OK, factionService.ztServerAddress(fid));
    }

    /**
     * 根据门派ID创建加密后的密文
     * 
     * @param fid
     * @return
     * @throws Exception
     */
    @Token
    @PostMapping("/encrypt")
    public ResponseResult<String> encrypt(@RequestParam Long fid) throws Exception {
        // 根据门派ID获取加密后的密文
        String encodeString = AESUtils.encodeASE(String.valueOf(fid));
        if (StringUtils.isNotBlank(encodeString)) {
            return new ResponseResult<>(ResponseMessage.OK, encodeString);
        }
        return new ResponseResult<>(ResponseMessage.CREATE_FAIL);
    }

    /**
     * 门派成员邀请
     * 
     * @param encryption
     *            加密的字符串
     * @return
     * @throws Exception
     */
    @Token
    @PostMapping("/invite")
    public ResponseResult<Long> invite(@RequestParam String encryption) throws Exception {
        // 对密文解密
        String decodeString = AESUtils.decodeASE(encryption);
        if (StringUtils.isBlank(decodeString)) {
            return new ResponseResult<>(ResponseMessage.INVITE_FAIL.getStatus(), "邀请码失效，请联系相关人员重新获取邀请码！");
        }
        if (decodeString.equals("LinkRot")) {
            return new ResponseResult<>(ResponseMessage.INVITE_FAIL.getStatus(), "邀请码已过期，请重新获取！");
        }
        Long fid = Long.parseLong(decodeString);
        // 获取用户的信息
        Long uid = (Long) request.getAttribute("userId");
        // 获取门派基本信息
        if (factionService.getById(fid) == null) {
            return new ResponseResult<>(ResponseMessage.DATA_NOT_FOUND.getStatus(), "门派不存在！");
        }
        // 根据门派ID和成员ID查询门派成员信息
        if (memberService.queryById(fid, uid) != null) {
            return new ResponseResult<>(ResponseMessage.OK.getStatus(), "您已是门派成员！", fid);
        }
        // 门派邀请
        if (!factionService.invite(fid, uid)) {
            return new ResponseResult<>(ResponseMessage.INVITE_FAIL);
        }
        return new ResponseResult<>(ResponseMessage.OK, fid);
    }

    /**
     * 根据门派ID获取季度年的起止时间
     * 
     * @param fid
     * @return
     * @throws Exception
     */
    @Token
    @GetMapping("/intervaldate")
    public ResponseResult<Map<String, Date>> intervalDate(@RequestParam Long fid) throws Exception {
        // 定义返回结果
        Map<String, Date> dateMap = new HashMap<>();
        // 获取该门派的季度年的开始月份
        Integer bmonth = factionService.getBmonthByFid(fid);
        if (bmonth != null && bmonth > 0) {
            OkrTaskUtil util = new OkrTaskUtil();
            // 获取当前时间所属的季度年的起止时间
            List<Date> dates = util.intervalDate(EgTimingType.YEAR_TARGET, new Date(), bmonth);
            if (dates != null && dates.size() > 0) {
                dateMap.put("btime", dates.get(0));
                dateMap.put("etime", dates.get(1));
            }
        }
        return new ResponseResult<>(ResponseMessage.OK, dateMap);
    }
}
